import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class ClientExamSystem {
    private Socket socket;
    private final Scanner SC = ClientScanner.sc;
    private Monitor monitor;

    public ClientExamSystem(Socket socket) {
        this.socket = socket;
    }

    // 返回值为是否结束运行

    /**
     * 主界面程序，每一个客户端连接后会进入这个程序
     * @param readThread 客户端的读取线程
     * @return 返回值为是否要结束运行
     */
    public boolean launch(ClientReadThread readThread) {
        monitor = readThread.monitor;
        String input ;
        do {
            do {

                Displayer.printMainFrame();
//                System.out.print("请输入操作号:");
                input = SC.nextLine();
            } while (!input.matches("[0123]"));
            switch (input) {
                case "0":
                    System.out.println("将会退出系统");
                    new ClientSendThread(socket, new Message("disconnect")).start();
                    break;
                case "1":
                    System.out.println("将进行登录");
                    login();
                    break;
                case "2":
                    System.out.println("将进行考生注册");
                    studentRegister();
                    break;
                case "3":
                    System.out.println("将进行管理员注册");
                    adminRegister();
                    break;
            }
        } while (!input.equals("0"));
        return true;
    }

    /**
     * 登录功能，提示用户输入，发给服务器校验，用户名密码正确则登录成功。
     * 登录成功会进入相应的界面/功能。
     * 有管理员和学生两种用户的登录以及对应的登录成功界面。
     */
    private void login() {
        User user = new User();
        String[] loginInfo = buildNewUserInfo("登录");
        user.setUserName(loginInfo[0]);
        user.setPassword(loginInfo[1]);
        synchronized (monitor.loginLock) {
            new ClientSendThread(socket, new Message("userCheck", user)).start();
            try {
                monitor.loginLock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (monitor.isLoginSuccess()) {
            User loginedUser = monitor.loginedUser;
            switch (monitor.userType) {
                case ADMINISTRATOR:
                    System.out.println("欢迎管理员登录");
                    monitor.setLoginSuccess(false);
                    adminSystem((Administrator) loginedUser);
                    break;
                case STUDENT:
                    System.out.println("欢迎学生登录");
                    monitor.setLoginSuccess(false);
                    studentSystem((Student) loginedUser);
                    break;
            }
        } else {
            System.out.println("用户名或密码错误！已退回至主界面。");
        }
    }

    public void adminRegister() {
        System.out.println("请输入root密码:");
        String input = inputJudge("[\\S]+");
        synchronized (monitor.checkRootLock) {
            new ClientSendThread(socket, new Message("checkRootPassword", new Command(input))).start();
            try {
                monitor.checkRootLock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (monitor.isRootPasswordIsRight()) {
            System.out.println("root密码正确");
            register(UserType.ADMINISTRATOR);
            monitor.setRootPasswordIsRight(false);
        }else {
            System.out.println("root密码错误。重试？(y/n)");
            String s = inputJudge("[yn]");
            if (s.equals("y")) {
                /*调用注册功能*/
                adminRegister();
            }
        }
    }

    public void studentRegister() {
        register(UserType.STUDENT);
    }
// admin 123456
    // admin

    /**
     * 提示用户输入，创建一个用户信息,包含用户名和密码。
     * @return 返回创建的信息的字符串数组。
     */
    private String[] buildNewUserInfo(String uses) {
        return ClientScanner.buildNewUserInfo(uses);
    }


    private String inputJudge( String regex) {
        return ClientScanner.inputJudge(regex);
    }

    /**
     * 注册功能，提示用户输入要使用的用户名和密码，发给服务器校验。
     * 收到服务器发回的校验结果后做出相应动作
     * @param userType 要注册的类型，有管理员和学生。
     */
    private void register(UserType userType) {
        String[] registerInfo = buildNewUserInfo("注册");
        HaveName user;
        System.out.println("用户名为:"+registerInfo[0]+"密码为:"+registerInfo[1]);
        System.out.println("你可以输入名字作为账号的昵称，如果输入'0'则昵称为你注册时的用户名。");
        String name = inputJudge("[0]|[\\S][\\S ]*[\\S]");
        if (name.equals("0")) name = registerInfo[0];
        boolean isRegisterSuccess = false;
        synchronized (monitor.registerLock) {
            switch (userType) {
                case ADMINISTRATOR:
                    user = new Administrator(registerInfo[0], registerInfo[1], name);
                    new ClientSendThread(socket, new Message("adminRegister",user)).start();
                    break;
                case STUDENT:
                    user = new Student(registerInfo[0], registerInfo[1], name);
                    new ClientSendThread(socket, new Message("studentRegister",user)).start();
                    break;
            }
            try {
                monitor.registerLock.wait();
                isRegisterSuccess = monitor.isRegisterSuccess();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        /*注册成功*/
        if (isRegisterSuccess) {
            System.out.println("注册成功！立即登录？(y/n)");
            String s = inputJudge("[yn]");
            if (s.equals("y")) {
                monitor.setRegisterSuccess(false);
                /*调用登录功能*/
                login();
            }
        }
        /*注册失败*/
        else {
            System.out.println("注册失败，用户名已经存在");
            System.out.print("重试？(y/n)");
            String s = inputJudge("[yn]");
            if (s.equals("y")) {
                /*调用注册功能*/
                register(userType);
            }
        }
    }

    private void adminSystem(Administrator admin) {
        AdminSystem as = new AdminSystem(socket, monitor, admin, sortQuestions(getAllQuestions()));
        as.launch();

    }

    private void studentSystem(Student student) {
        StudentSystem ss = new StudentSystem(socket, monitor, student, sortQuestions(getAllQuestions()));
        ss.launch();
    }

    public List<HaveAnswer> getAllQuestions() {
        synchronized (monitor.getAllQuestionsLock) {
            new ClientSendThread(socket, new Message("getAllQuestions")).start();
            try {
                monitor.getAllQuestionsLock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return monitor.getAllQuestions();
    }

    public List<?>[] sortQuestions(List<HaveAnswer> allQuestions) {
        List<TrueOrFalseQuestion> trueOrFalseQuestionList = new ArrayList<>();
        List<ChoiceQuestion> choiceQuestionList = new ArrayList<>();
        for (HaveAnswer item : allQuestions) {
            if (item instanceof ChoiceQuestion) {
                choiceQuestionList.add((ChoiceQuestion) item);
            }else {
                trueOrFalseQuestionList.add((TrueOrFalseQuestion) item);
            }
        }
        return new List<?>[]{choiceQuestionList, trueOrFalseQuestionList};
    }
}
